unit Engine;

interface

uses DGLE, DGLE_Base, DGLE_Types;

const
  APP_CAPT = 'Heart of Darkness RL';
  DLL_PATH = 'DGLE.dll';

  BUTTON_WIDTH  = 250;
  BUTTON_HEIGHT = 50;

  ITEMS_COUNT = 5;
  ITEM_SIZE = 32;

  TILES_COUNT = 1;

  TILE_SIZE = 64;

  CREATURES_COUNT = 2;

  MAP_WIDTH  = 128;
  MAP_HEIGHT = 128;

var
  SCREEN_WIDTH: Cardinal  = 1024;
  SCREEN_HEIGHT: Cardinal = 768;
  GAME_SCR_WIDTH: Cardinal = 17;
  GAME_SCR_HEIGHT: Cardinal = 13;
  MAP_TOP: Integer = 0;
  MAP_LEFT: Integer = 0;
  SCR_TOP: Integer = 0;
  SCR_LEFT: Integer = 0;
  CURRENT_ALLY: Integer = 0;

var
  prevWindowWidth, prevWindowHeight: Cardinal;
  MousePos: TPoint2;
  ScreenPos: TPoint2;
  LeftButton: Boolean;
  RightButton: Boolean;

var
  GameTick: Double = 0.0;

var
  pEngineCore    : IEngineCore       = nil;
  pResMan        : IResourceManager  = nil;
  pRender2D      : IRender2D         = nil;
  pRender        : IRender           = nil;
  pInput         : IInput            = nil;
  pFont11        : IBitmapFont       = nil;
  pFont12        : IBitmapFont       = nil;
  pFont18        : IBitmapFont       = nil;
  pFont24        : IBitmapFont       = nil;
  pCursor        : ITexture          = nil;

type
  TRect = record
    X, Y, Width, Height: Integer;
  end;

procedure OnFullScreenEvent(pParametr: Pointer; const pEvent: IBaseEvent); stdcall;
procedure Init;
procedure Render;
procedure Update;
procedure Free;
procedure TextOut(X, Y: Word; S: string; C: TColor4); overload;
procedure TextOut(X, Y: Word; I: Integer; C: TColor4); overload;
function Rect(X,Y,W,H : integer):TRect;
function RectInRect(r:Trect;r2:Trect):boolean;
function Rand(A, B: Integer): Integer;
function BarWidth(CX, MX, WX: Integer): Integer;
function StrToPAChar( const value : string ): PAnsiChar;

implementation

uses SysUtils, SceneEngine;

var
  LTime, RTime: Integer;

procedure OnFullScreenEvent(pParametr: Pointer; const pEvent: IBaseEvent); stdcall;
var
  res_width, res_height: Cardinal;
  p_event: IEvGoFullScreen;
  go_fscreen: Boolean;
begin
  p_event := IEvGoFullScreen(pEvent);
  p_event.GetResolution(res_width, res_height, go_fscreen);

  if (go_fscreen) then
  begin
    prevWindowWidth := res_width;
    prevWindowHeight := res_height;
    pEngineCore.GetDesktopResolution( res_width, res_height);
    p_event.SetResolution(res_width, res_height);
  end else p_event.SetResolution(prevWindowWidth, prevWindowHeight);
end;

procedure Init;
begin
  pEngineCore.GetSubsystem(ESS_RESOURCE_MANAGER, IEngineSubSystem(pResMan));
  pEngineCore.GetSubsystem(ESS_RENDER, IEngineSubSystem(pRender));
  pEngineCore.GetSubsystem(ESS_INPUT,  IEngineSubSystem(pInput));
  pRender.GetRender2D(pRender2D);
  pInput.Configure(ICF_HIDE_CURSOR);   
  pResMan.Load('Resources\Sprites\Fonts\11.dft', IEngineBaseObject(pFont11), BFLF_GENERATE_MIPMAPS);
  pResMan.Load('Resources\Sprites\Fonts\12.dft', IEngineBaseObject(pFont12), BFLF_GENERATE_MIPMAPS);
  pResMan.Load('Resources\Sprites\Fonts\18.dft', IEngineBaseObject(pFont18), BFLF_GENERATE_MIPMAPS);
  pResMan.Load('Resources\Sprites\Fonts\24.dft', IEngineBaseObject(pFont24), BFLF_GENERATE_MIPMAPS);
  pResMan.Load('Resources\Sprites\Cursors\Default.png', IEngineBaseObject(pCursor), TEXTURE_LOAD_DEFAULT_2D);
  pCursor.SetFrameSize(32, 32);
  SceneEngine.Init;
end;

function BarWidth(CX, MX, WX: Integer): Integer;
var
  I: Integer;
begin
  if (CX = MX) and (CX = 0) then begin Result := 0; Exit; end;
  if (MX <= 0) then MX := 1;
  I := (CX * WX) div MX;
  if (I <= 0) then I := 0;
  if (CX >= MX) then I := WX;
  Result := I;
end;

procedure Render;
var
  P: TPoint2;
begin
  pRender2D.Begin2D();
  SceneMan.Render;
  pRender2D.AbsoluteToResolutionCorrect(MousePos, P);
  pRender2D.DrawTextureSprite(pCursor, Point2(P.X, P.Y), Point2(32.0, 32.0), 0, 0.0, EF_BLEND);
  pRender2D.End2D();
end;

procedure Update;
var
  S: TMouseStates;
begin
  SceneMan.Update;

  pInput.GetMouseStates(S);
  MousePos := Point2(S.iX, S.iY);
  ScreenPos := Point2((S.iX - SCR_LEFT) div TILE_SIZE,
    (S.iY - SCR_TOP) div TILE_SIZE);

  Dec(LTime);
  if S.bLeftButton then LTime := 20;
  if (not S.bLeftButton) and (LTime > 0) then
  begin
    LeftButton := True;
    LTime := 0;
  end else LeftButton := False;

  Dec(RTime);
  if S.bRightButton then RTime := 20;
  if (not S.bRightButton) and (RTime > 0) then
  begin
    RightButton := True;
    RTime := 0;
  end else RightButton := False;
end;

procedure Free;
begin
  SceneEngine.Free;
  pFont24     := nil;
  pFont18     := nil;
  pFont12     := nil;
  pFont11     := nil;
  pCursor     := nil;
  pRender2D   := nil;
  pInput      := nil;
  pRender     := nil;
  pResMan     := nil;
  pEngineCore := nil;
end;

function Rect(X, Y, W, H: Integer): TRect;
begin
  result.X:=X;
  result.Y:=Y;
  result.Width:=W;
  result.Height:=H;
end;

function RectInRect(r:Trect;r2:Trect):boolean;
begin
  Result:=
    (R.X < R2.X+R2.Width) and
    (R.X+R.Width > R2.X) and
    (R.Y < R2.Y+R2.Height) and
    (R.Y+R.Height > R2.Y) or
    (R2.X < R.X+R.Width) and
    (R2.X+R2.Width > R.X) and
    (R2.Y < R.Y+R.Height) and
    (R2.Y+R2.Height > R.Y);
end;

function FloatToPACar( const value : Extended ): PAnsiChar;
begin
  Result := PAnsiChar( AnsiString( FloatToStr( value )));
end;

function IntToPAChar( const value : Integer ): PAnsiChar;
begin
  Result := PAnsiChar( AnsiString( IntToStr( value )));
end;

function StrToPAChar( const value : string ): PAnsiChar;
begin
  Result := PAnsiChar( AnsiString( value ));
end;

function BoolToPAChar( const value : Boolean ): PAnsiChar;
begin
  case value of
    True:  Result := 'True';
    else Result := 'False';
  end;
end;

procedure TextOut(X, Y: Word; S: string; C: TColor4);
var
  W, H: Cardinal;
begin
  pFont12.GetTextDimensions(StrToPAChar(S), W, H);
  pFont12.Draw2DSimple(X, Y, StrToPAChar(S), C);
end;

procedure TextOut(X, Y: Word; I: Integer; C: TColor4);
begin
  TextOut(X, Y, IntToStr(I), C);
end;

function Rand(A, B: Integer): Integer;
begin
  Result := Round(Random(B - A + 1) + A);
end;

end.
